Article body
Recently, I discovered an ajax asynchronous request. When using PHP.post, $ .get, or $ .ajax to request a PHP server, the data cannot always be returned asynchronously.
After several tests, I found that:
-different browsers request different domain names-no blocking: no experiment required
-different browsers, request the same domain name-no blocking: session_id () returns different
-same browser, request different domain names- Non-blocking: session_id returns different
-same browser, requesting the same domain name-blocking: session_id () returns the same
found problems:
1 close XDEBUG
2 SESSION lock
3 clear output buffer
1 close XDEBUG
XDEBUG is real-time debugging. When debugging, it will maintain the FPM to ensure that the thread is working to avoid data pollution.
A typical test method is to use XDEBUG to debug, open another browser and visit the site, the site is not accessible at this time.
This has a significant impact on parallel responses, that is, even if the front end sends multiple requests, it is controlled by XDEBUG and can only respond to one at the same time.
Also, because XDEBUG relies on SESSION, even if you use session_write_close (), close the session lock (see below).
XDEBUG will still open automatically.
2 SESSION lock
Use session_write_close () to close the write lock of SESSION, which is suitable for the case where SESSION is saved as a file.
Not required if SESSION is stored in Redis.
3 Clear the output buffer
Using session_write_close () may not close the SESSION lock immediately, so add: ob_end_flush () before this method.
Let session_write_close () take effect immediately.
4 Example
There is an example below. When you click the [Submit] button, the front end will send two requests to the background server.
One is a get request, which is requested every 1 second.
One is a post request, which is sent once at the beginning and then waits for the corresponding end.
Take a look at the HTML code
session_start();
$action = $_GET['action'];
if ($action == 'post') {
$_SESSION['time'] = 0;
session_write_close();
while ($_SESSION['time'] < 5) {
session_start();
$_SESSION['time'] = $_SESSION['time'] + 1;
// 将SESSION数据写入文件中,并关闭写锁
session_write_close();
// sleep()模拟花费时间较长的程序,这样在关闭写锁之后,
// 服务器就能够相应别的请求,如下的$action=get,
sleep(1);
}
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}
if ($action == 'get') {
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}
php code
$_SESSION['time']]);
exit();
}
if ($action == 'get') {
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}
文章正文
最近發現了一個ajax異步請求的問題,用$.post、$.get、$.ajax請求PHP服務器時,總是無法異步返回數據。
經多次測試才發現:
—不同瀏覽器,請求不同域名-不阻塞:無需實驗
—不同瀏覽器,請求同域名-不阻塞:session_id()返回不同
—同一瀏覽器,請求不同域名-不阻塞:session_id返回不同
—同一瀏覽器,請求同域名-阻塞:session_id()返回相同
發現問題所在:
1關閉XDEBUG
2 SESSION鎖
3清除輸出緩衝區
1 關閉XDEBUG
XDEBUG是實時調試。調試時,它將保持FPM以確保線程正在工作以避免數據污染。
典型的測試方法是,使用XDEBUG進行調試時,打開另一個瀏覽器並訪問該站點,該站點這個時候是無法訪問的。
這對並行響應有重大影響,即,即使前端發送多個請求,它也受XDEBUG控制,並且只能同時響應一個。
另外,由於XDEBUG依賴於SESSION,因此即使您使用session_write_close(),也要關閉會話鎖(請參見下文)。
XDEBUG仍會自動打開。
2 SESSION鎖
用session_write_close()關閉SESSION的寫鎖,這適合SESSION保存為File的情況。
如果SESSION保存在Redis,則不需要。
3 清除輸出緩衝區
使用session_write_close()可能無法立即關閉SESSION鎖,所以在這個方法之前加上:ob_end_flush()。
讓session_write_close()馬上生效。
4 示例
有如下一個範例,當點擊【提交】按鈕時,前端會給後台服務器發送兩種請求。
一種是get請求,每隔1秒請求一次。
一種是post請求,最開始的時候發送一次,然後等待相應結束。
看看HTML代碼
session_start();
$action = $_GET['action'];
if ($action == 'post') {
$_SESSION['time'] = 0;
session_write_close();
while ($_SESSION['time'] < 5) {
session_start();
$_SESSION['time'] = $_SESSION['time'] + 1;
// 将SESSION数据写入文件中,并关闭写锁
session_write_close();
// sleep()模拟花费时间较长的程序,这样在关闭写锁之后,
// 服务器就能够相应别的请求,如下的$action=get,
sleep(1);
}
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}
if ($action == 'get') {
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}
php代碼
$_SESSION['time']]);
exit();
}
if ($action == 'get') {
echo json_encode([session_id() => $_SESSION['time']]);
exit();
}